/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "PlayerSettings.h"
#include "StringBuilder.h"
#include "Error.h"
#include "Logger.h"
#include "Table.h"
#include "color.h"
#include "myassert.h"

#include <string.h>

using namespace Chronos;
using namespace std;

static const char* DELIMITER = "\n";

PlayerSettings::Setting::Setting(const std::string& name_, const std::string& option1, const std::string& option2)
    : name(name_)
{
    options.push_back(option1);
    options.push_back(option2);
    currentOption = option1;
}

void PlayerSettings::Setting::setCurrent(const std::string& option) {
    for(OptionsConstIter iter=options.begin(); iter!=options.end(); ++iter) {
        if (*iter == option) {
            currentOption = option;
            return;
        }
    }
    LOG(WARN, "PlayerSettings::%s() Unknown option '%s', ignoring", __func__, option.c_str());
}

void PlayerSettings::Setting::setCurrent(StringBuilder& buffer, const std::string& option) {
    for(OptionsConstIter iter=options.begin(); iter!=options.end(); ++iter) {
        if (*iter == option) {
            currentOption = option;
            return;
        }
    }
    buffer << "Unknown option. Valid options are " << printOptions() << '\n';
}

string PlayerSettings::Setting::printOptions() const {
    StringBuilder buffer;
    buffer << '<';
    for(OptionsConstIter iter=options.begin(); iter!=options.end(); ++iter) {
        if (iter != options.begin()) buffer << ',';
        if (*iter == currentOption) 
            buffer << ANSI_WHITE << *iter << ANSI_NORMAL;
        else 
            buffer << *iter;
    }
    buffer << '>';
    return string(buffer); 
}


PlayerSettings::PlayerSettings() {}


void PlayerSettings::add(const char* setting, const char* option1, const char* option2) {
    settings.push_back(Setting(setting, option1, option2));
}


const string& PlayerSettings::getOption(const string& setting) const {
    const Setting* s = find(setting);
    if (s == 0) throw MudError("Unknown setting: " + setting);
    return s->currentOption;
}


void PlayerSettings::setOption(StringBuilder& buffer, const string& setting, const string& option) {
    Setting* s = find(setting);
    if (s == 0) {
        buffer << "Unknown setting. Type 'settings' for a list of settings\n";
        return;
    }
    s->setCurrent(buffer, option);
}


const PlayerSettings::Setting* PlayerSettings::find(const string& setting) const {
    for (SettingsConstIter iter = settings.begin(); iter!=settings.end(); ++iter) {
        if (iter->name == setting) return &(*iter);
    }
    return 0;
}


PlayerSettings::Setting* PlayerSettings::find(const string& setting) {
    for (SettingsIter iter = settings.begin(); iter!=settings.end(); ++iter) {
        if (iter->name == setting) return &(*iter);
    }
    return 0;
}


void PlayerSettings::print(StringBuilder& buffer) const {
    buffer << "settings:\n";
    Table table(2);
    for (SettingsConstIter iter=settings.begin(); iter!=settings.end(); ++iter) {
        table.addCell(iter->name);
        table.addCell(iter->printOptions());
    }
    table.write(buffer);
}


void PlayerSettings::initialize(const string& init) {
    if (init == "") return;

    char buf[init.length()+1];
    strcpy(buf, init.c_str());
    char* key = strtok(buf, DELIMITER); 
    while (key != 0) {
        char* value = strtok(0, DELIMITER);
        ASSERT_NOT_NULL(value);
        Setting* s = find(key);
        if (s == 0) {
            LOG(WARN, "PlayerSettings::%s() unknown setting '%s', skipping", __func__, key);
        } else {
            s->setCurrent(value);
        }
        key = strtok(0, DELIMITER); 
    }
}


string PlayerSettings::toString() const {
    StringBuilder buffer;
    for (SettingsConstIter iter=settings.begin(); iter!=settings.end(); ++iter) {
        buffer << iter->name << DELIMITER << iter->currentOption << DELIMITER;
    }
    return string(buffer);
}

